#include <stdio.h>
#include <inttypes.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_chip_info.h"
#include "esp_flash.h"
#include "oled.h"
#include "esp_timer.h"

#include "RC522_IC/bsp_rc522.h"

#include "bsp_relay.h"
#include "string.h"
#include "esp_private/esp_task_wdt.h"
#include "esp_private/esp_task_wdt_impl.h"

#include "nvs_flash.h"
#include "esp_netif.h"
#include "esp_event.h"
#include "esp_log.h"
#include "MQTT/mqtt_ssl.h"
#include "cJSON.h"
#include "mqtt_client.h"

static const char *TAG = "mqtts_example";
/* 卡的ID存储，32位,4字节 */
u8 ucArray_ID[4];
uint8_t ucStatusReturn; // 返回状态
char card_id[12];
uint8_t read_write_data[16] = {0};                          // 读写数据缓存
uint8_t *read_data=read_write_data;
extern char new_card_id[12];

// 引用mqtt句柄
extern esp_mqtt_client_handle_t client;

static void RFID_task(void *pvParameters);
static void OLED_task(void *pvParameters);
static void RELAY_task(void *pvParameters);

void app_main(void)
{
    OLED_Init(); // 初始化OLED
    OLED_Clear();
    OLED_ShowString(0, 0, (unsigned char *)"wifi...", 16, 1);
    OLED_Refresh();
    /////////////////////////////////////////////////////////////////////////////////////

    printf("Init\r\n");
    RC522_Init(); // IC卡IO口初始化
    RC522_Rese(); // 复位RC522
    printf("Start\r\n");
    /////////////////////////////////////////////////////////////////////////////////////////
    esp_task_wdt_deinit();
    Relay_GPIO_Init(); // 继电器初始化

    ESP_LOGI(TAG, "[APP] Startup..");
    ESP_LOGI(TAG, "[APP] Free memory: %" PRIu32 " bytes", esp_get_free_heap_size());
    ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version());

    esp_log_level_set("*", ESP_LOG_INFO);
    esp_log_level_set("esp-tls", ESP_LOG_VERBOSE);
    esp_log_level_set("mqtt_client", ESP_LOG_VERBOSE);
    esp_log_level_set("mqtt_example", ESP_LOG_VERBOSE);
    esp_log_level_set("transport_base", ESP_LOG_VERBOSE);
    esp_log_level_set("transport", ESP_LOG_VERBOSE);
    esp_log_level_set("outbox", ESP_LOG_VERBOSE);

    ESP_ERROR_CHECK(nvs_flash_init());
    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK(esp_event_loop_create_default());

    /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig.
     * Read "Establishing Wi-Fi or Ethernet Connection" section in
     * examples/protocols/README.md for more information about this function.
     */
    ESP_ERROR_CHECK(example_connect());

    mqtt_app_start();
    /*-------------------------- 创建线程 ---------------------------*/
    xTaskCreate(RFID_task, "RFID_task", 2048, NULL, 4, NULL);
    xTaskCreate(OLED_task, "OLED_task", 2048, NULL, 5, NULL);
    xTaskCreate(RELAY_task, "RELAY_task", 4096, NULL, 6, NULL);
}

static void RFID_task(void *pvParameters)
{
    int i = 0;


    uint8_t card_KEY[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; // 默认密码

    while (1) // 任务都是一个无限循环，不能返回
    {
        /* 寻卡（方式：范围内全部），第一次寻卡失败后再进行一次，寻卡成功时卡片序列传入数组ucArray_ID中 */
        if ((ucStatusReturn = PcdRequest(PICC_REQALL, ucArray_ID)) != MI_OK)
        {
            ucStatusReturn = PcdRequest(PICC_REQALL, ucArray_ID);
        }

        if (ucStatusReturn == MI_OK)
        {
            /* 防冲突操作，被选中的卡片序列传入数组ucArray_ID中 */
            if (PcdAnticoll(ucArray_ID) == MI_OK)
            {
                // 输出卡ID
                printf("ID: %X %X %X %X\r\n", ucArray_ID[0], ucArray_ID[1], ucArray_ID[2], ucArray_ID[3]);
                sprintf(card_id, "%X%X%X%X", ucArray_ID[0], ucArray_ID[1], ucArray_ID[2], ucArray_ID[3]);

                // 选卡
                if (PcdSelect(ucArray_ID) != MI_OK)
                {
                    printf("PcdSelect failure\r\n");
                }

                // 校验卡片密码
                // 数据块6的密码A进行校验（所有密码默认为16个字节的0xff）
                if (PcdAuthState(PICC_AUTHENT1A, 6, card_KEY, ucArray_ID) != MI_OK)
                {
                    printf("PcdAuthState failure\r\n");
                }

                // 往数据块4写入数据read_write_data
                read_write_data[0] = 0xaa; // 将read_write_data的第一位数据改为0xaa
                if (PcdWrite(4, read_write_data) != MI_OK)
                {
                    printf("PcdWrite failure\r\n");
                }

                // 将read_write_data的16位数据，填充为0（清除数据的意思）
                for (int i = 0; i < 16; i++)
                {
                    read_write_data[i] = 0;
                }
                delay_us(8);

                // 读取数据块4的数据
                if (PcdRead(4, read_write_data) != MI_OK)
                {
                    printf("PcdRead failure\r\n");
                }

                // 输出读出的数据
                for (i = 0; i < 16; i++)
                {
                    printf("%x ", read_write_data[i]);
                }
                printf("\r\n");
            }
        }
        vTaskDelay(50 / portTICK_PERIOD_MS); // 100ms
    }
}
static void OLED_task(void *pvParameters)
{

    while (1)
    {
        // OLED_ShowString(0,0,(unsigned char*)"ABC",8,1);//6*8 “ABC”
        // OLED_ShowString(0,8,(unsigned char *)"ABC",12,1);//6*12 “ABC”
        // OLED_ShowString(0,20,(unsigned char *)"ABC",16,1);//8*16 “ABC”
        // OLED_ShowString(0,36,(unsigned char *)"ABC",24,1);//12*24 “ABC”

        // OLED_ShowChinese(54,0,3,16,1);//电
        // OLED_ShowChinese(72,0,4,16,1);//子
        // OLED_ShowChinese(90,0,5,16,1);//技
        // OLED_ShowChinese(108,0,6,16,1);//术
        if (strlen(card_id) > 0)
        {
            if (strcmp(card_id, new_card_id) == 0)
            {
                printf("验证通过，门已开\r\n");
                OLED_Clear();
                OLED_ShowString(0, 0, (unsigned char *)"Verification", 16, 1);
                OLED_ShowString(0, 16, (unsigned char *)"passed", 16, 1);
                OLED_ShowString(0, 32, (unsigned char *)"Door", 16, 1);
                OLED_ShowString(0, 48, (unsigned char *)"OPEN", 16, 1);
                OLED_Refresh();
                Set_Relay_Switch(1); // 控制继电器吸合
                vTaskDelay(4000 / portTICK_PERIOD_MS);
            }
            else
            {
                printf("验证未通过\r\n");
                OLED_Clear();
                OLED_ShowString(0, 0, (unsigned char *)"Verification", 16, 1);
                OLED_ShowString(0, 16, (unsigned char *)"Fail", 16, 1);
                OLED_ShowString(0, 32, (unsigned char *)"Door", 16, 1);
                OLED_ShowString(0, 48, (unsigned char *)"CLOSED", 16, 1);
                OLED_Refresh();
                Set_Relay_Switch(0); // 控制继电器断开
            }
            memset(card_id, 0, sizeof(card_id)); // 清空卡号缓存
        }
        else
        {
            // 如果卡号为空，显示请刷卡（英文）
            OLED_ShowString(0, 0, (unsigned char *)"Please Swipe", 16, 1);
            OLED_ShowString(0, 16, (unsigned char *)"Card", 16, 1);
            OLED_ShowString(0, 32, (unsigned char *)"Door", 16, 1);
            OLED_ShowString(0, 48, (unsigned char *)"CLOSED", 16, 1);
            OLED_Refresh();
            Set_Relay_Switch(0); // 控制继电器断开
        }

        vTaskDelay(500 / portTICK_PERIOD_MS); // 500ms延时
    }
}

static void RELAY_task(void *pvParameters)
{
    while (1)
    {    
    
// esp_mqtt_client_subscribe(client, "/readcard", 0);

    }
}